package hell.satan.droidbdf.base;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.View;

import java.lang.ref.WeakReference;

import hell.satan.droidbdf.utils.Generator;
import hell.satan.droidbdf.utils.LogWrapper;

/**
 * 所有Fragment的基类
 * Super class for all fragments
 *
 * @author Cerberus
 */
@SuppressWarnings("unused")
public class BaseFragment extends Fragment {
    protected final String TAG = getClass().getSimpleName();

    protected static final Generator GENERATOR = new Generator();

    private FragmentHandler mHandler;
    private OnFragmentInteractionListener mListener;

    public BaseFragment() {
        mHandler = new FragmentHandler(this);
    }

    @CallSuper
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        LogWrapper.v(TAG, "onAttach");
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            Exception ex = new RuntimeException(context
                    + " had batter implement OnFragmentInteractionListener");
            LogWrapper.w(TAG, ex);
        }
    }

    @CallSuper
    @Override
    public void onCreate(@Nullable Bundle state) {
        super.onCreate(state);
        LogWrapper.v(TAG, "onCreate");
    }

    @CallSuper
    @Override
    public void onViewCreated(View view, @Nullable Bundle state) {
        super.onViewCreated(view, state);
        LogWrapper.v(TAG, "onViewCreated");
    }

    @CallSuper
    @Override
    public void onActivityCreated(@Nullable Bundle state) {
        super.onActivityCreated(state);
        LogWrapper.v(TAG, "onActivityCreated");
    }

    @CallSuper
    @Override
    public void onStart() {
        super.onStart();
        LogWrapper.v(TAG, "onStart");
    }

    @CallSuper
    @Override
    public void onResume() {
        super.onResume();
        LogWrapper.v(TAG, "onResume");
    }

    @CallSuper
    @Override
    public void onPause() {
        LogWrapper.v(TAG, "onPause");
        super.onPause();
    }

    @CallSuper
    @Override
    public void onStop() {
        LogWrapper.v(TAG, "onStop");
        super.onStop();
    }

    @CallSuper
    @Override
    public void onDestroyView() {
        LogWrapper.v(TAG, "onDestroyView");
        super.onDestroyView();
    }

    @CallSuper
    @Override
    public void onDestroy() {
        LogWrapper.v(TAG, "onDestroy");
        super.onDestroy();
    }

    @CallSuper
    @Override
    public void onDetach() {
        LogWrapper.v(TAG, "onDetach");
        super.onDetach();
    }

    /**
     * 与{@link android.os.Handler#handleMessage(android.os.Message)}方法功能完全相同，
     * 你可以直接把此Fragment当作{@link android.os.Handler}使用，覆盖此方法即可
     * <p/>
     * Same as {@link android.os.Handler#handleMessage(android.os.Message)},
     * you can take this fragment as a {@link android.os.Handler}, just need to override this method
     *
     * @see android.os.Handler#handleMessage(android.os.Message)
     */
    @CallSuper
    protected void handleMessage(Message msg) {
    }

    public final boolean sendEmptyMessage(int what) {
        return mHandler.sendEmptyMessage(what);
    }

    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        return mHandler.sendEmptyMessageDelayed(what, delayMillis);
    }

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        return mHandler.sendEmptyMessageAtTime(what, uptimeMillis);
    }

    public final boolean sendMessage(Message msg) {
        return mHandler.sendMessage(msg);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis) {
        return mHandler.sendMessageDelayed(msg, delayMillis);
    }

    public final boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        return mHandler.sendMessageAtTime(msg, uptimeMillis);
    }

    public final boolean hasMessages(int what) {
        return mHandler.hasMessages(what);
    }

    public final void removeMessages(int what) {
        mHandler.removeMessages(what);
    }

    public final void post(Runnable r) {
        mHandler.post(r);
    }

    public final boolean postDelayed(Runnable run, long delayMillis) {
        return mHandler.postDelayed(run, delayMillis);
    }

    public final boolean postAtTime(Runnable run, Object token, long uptimeMillis) {
        return mHandler.postAtTime(run, token, uptimeMillis);
    }

    public final boolean postAtTime(Runnable run, long uptimeMillis) {
        return mHandler.postAtTime(run, uptimeMillis);
    }

    public final void removeCallbacks(Runnable run) {
        mHandler.removeCallbacks(run);
    }

    @Nullable
    protected Bundle performInteraction(@Nullable Bundle data) {
        return mListener == null ? null : mListener.onFragmentInteraction(this, data);
    }

    /**
     * 用于Fragment向Activity通信的接口，只需Activity实现此接口即可，BaseFragment会自动进行绑定
     * Interface for Fragment to Activity Communications
     */
    public interface OnFragmentInteractionListener {
        /**
         * 用于Fragment主动向Activity发起通信交互
         * Communication interaction for Fragment and Activity
         *
         * @param fragment 发起通信的Fragment
         *                 The fragment which intent to interaction
         * @param data     Fragment向Activity传递的数据，可以为空，但不建议这样做
         *                 Data from fragment to activity, may be null
         * @return Activity向Fragment回传的处理结果，可以为空 Result from activity, may be null
         */
        @Nullable
        Bundle onFragmentInteraction(BaseFragment fragment, @Nullable Bundle data);
    }

    private static class FragmentHandler extends Handler {
        private final String TAG;
        private WeakReference<BaseFragment> mActivity;

        public FragmentHandler(BaseFragment fragment) {
            super(Looper.getMainLooper());
            TAG = String.format("%1$s$%2$s", fragment.getClass().getSimpleName(), getClass().getSimpleName());
            mActivity = new WeakReference<>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            LogWrapper.v(TAG, msg.toString());
            BaseFragment fragment = mActivity.get();
            if (fragment != null) {
                fragment.handleMessage(msg);
            } else {
                LogWrapper.v(TAG, "Fragment has already been recycled, message been abandoned.");
            }
        }
    }
}
